package cn.lxg.utils;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import cn.lxg.dao.entity.Lottery;
import cn.lxg.dao.entity.SuperLottery;
import cn.lxg.dao.mapper.LotteryMapper;
import cn.lxg.dao.mapper.SuperLotteryMapper;
import cn.lxg.vo.SuperWinLotteryVo;
import cn.hutool.core.collection.CollectionUtil;
import cn.lxg.vo.WinLotteryVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.micrometer.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class SuperLotteryBallUtils  {

    @Autowired
    private SuperLotteryMapper superLotteryMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final List<Integer> redBallList = new CopyOnWriteArrayList<>();
    private static final List<Integer> blueBallList = new CopyOnWriteArrayList<>();


    static {
        // 红球的号码范围是1到35
        for (int i = 1; i <= 35; i++) {
            redBallList.add(i);
        }
        for (int i = 1; i <= 12; i++) {
            blueBallList.add(i);
        }
    }




    /**
     * 查看符合这些条件的差多少期次
     *
     * @param historyWin 历史数据
     * @param redCount   红球相等多少个
     * @param blueCount  篮球相等数量
     * @return
     */
    public SuperWinLotteryVo getAllDiffPeriodList(List<SuperWinLotteryVo> historyWin, Integer redCount, Integer blueCount, SuperWinLotteryVo winLotteryVo) {
        String redBlueCache = redisTemplate.opsForValue().get("SuperLottery" + "redCount" + redCount + "blueCount" + blueCount);
        List<Long> result = new ArrayList<>();
        if (StringUtils.isNotBlank(redBlueCache)) {
            result = JSONUtil.toList(redBlueCache, Long.class);
        } else {
            Map<Long, Long> map = new HashMap<>();
            for (int a = 0; a < historyWin.size() - 1; a++) {
                SuperWinLotteryVo outLoop = historyWin.get(a);
                for (int b = a + 1; b < historyWin.size(); b++) {
                    SuperWinLotteryVo inLoop = historyWin.get(b);
                    if (RangeUtil.getCommonElementsCount(outLoop.getRedBall(), inLoop.getRedBall()) == redCount && (Objects.isNull(blueCount) || RangeUtil.getCommonElementsCount(outLoop.getBlueBall(), inLoop.getBlueBall()) > blueCount)) {
                        map.put(outLoop.getCode(), inLoop.getCode());
                        break;
                    }
                }
            }
            for (Long code : map.keySet()) {
                LambdaQueryWrapper<SuperLottery> wrapper = new LambdaQueryWrapper<>();
                wrapper.between(SuperLottery::getCode, map.get(code), code);
                Long aLong = superLotteryMapper.selectCount(wrapper);
                result.add(aLong);
            }
            redisTemplate.opsForValue().set("SuperLottery" + "redCount" + redCount + "blueCount" + blueCount, JSONUtil.toJsonStr(result),10, TimeUnit.MINUTES);
        }

        if (CollectionUtil.isEmpty(result)) {
            for (SuperWinLotteryVo history : historyWin) {
                if (RangeUtil.getCommonElementsCount(history.getRedBall(), winLotteryVo.getRedBall()) == redCount && (Objects.isNull(blueCount) || RangeUtil.getCommonElementsCount(history.getRedBall(), winLotteryVo.getRedBall()) == blueCount)) {
                    return null;
                }
            }
            return winLotteryVo;
        }

        Integer asDouble = Double.valueOf(result.stream().mapToLong(s -> s).average().getAsDouble() - CollectionUtil.min(result)).intValue();
        if (asDouble <= 1) {
            return winLotteryVo;
        }
        List<SuperWinLotteryVo> recentWinLotteryVos1200 = CollectionUtil.split(historyWin, asDouble).get(0);
        for (SuperWinLotteryVo history : recentWinLotteryVos1200) {
            if (RangeUtil.getCommonElementsCount(history.getRedBall(), winLotteryVo.getRedBall()) == redCount && (Objects.isNull(blueCount) || RangeUtil.getCommonElementsCount(history.getRedBall(), winLotteryVo.getRedBall()) == blueCount)) {
                return null;
            }
        }
        return winLotteryVo;
    }

    /**
     * @param redCannotAppearNum  不能出现的红球
     * @param blueCannotAppearNum 不能出现的篮球
     * @param maxAndMinRange      红球篮球总和范围
     * @param historyWin          历史数据
     * @return
     */
    public SuperWinLotteryVo getWinLottery(Set<Integer> redCannotAppearNum, Set<Integer> blueCannotAppearNum, List<Integer> maxAndMinRange, List<SuperWinLotteryVo> historyWin) {

        //最近的红球都不行
        SuperWinLotteryVo winLotteryVo1 = CollectionUtil.split(historyWin, 1).get(0).get(0);
        redCannotAppearNum.addAll(winLotteryVo1.getRedBall());

        blueCannotAppearNum.addAll(winLotteryVo1.getBlueBall());

        //是否应该出现
        List<Integer> redBalls = getRedBalls();
        if (CollectionUtil.isNotEmpty(CollectionUtil.intersection(redCannotAppearNum, redBalls)) || RangeUtil.getConsecutiveGroupsCount(redBalls) >= 3 || RangeUtil.getConsecutiveGroupsCountNum(redBalls) >= 2) {
            return null;
        }
        List<Integer> blueBalls = getBlueBall();
        if (CollectionUtil.isNotEmpty(CollectionUtil.intersection(blueCannotAppearNum, blueBalls)) || RangeUtil.getConsecutiveGroupsCount(blueBalls) >= 2) {
            return null;
        }
        //在不在范围内
        int sum = redBalls.stream().mapToInt(s -> s).sum() + blueBalls.stream().mapToInt(s -> s).sum();
        Integer min = maxAndMinRange.get(0);
        Integer max = maxAndMinRange.get(1);
        if (sum < min || sum > max) {
            return null;
        }
        SuperWinLotteryVo winLotteryVo = new SuperWinLotteryVo();
        winLotteryVo.setRedBall(redBalls);
        winLotteryVo.setBlueBall(blueBalls);
        //是否和历史数据相同
        for (SuperWinLotteryVo history : historyWin) {
            if (CollectionUtil.isEqualList(history.getRedBall(), winLotteryVo.getRedBall()) && CollectionUtil.isEqualList(history.getBlueBall(), winLotteryVo.getBlueBall())) {
                return null;
            }
        }

        //是否和历史数据相同
        for (SuperWinLotteryVo history : historyWin) {
            // 5 + 2
            if (CollectionUtil.isEqualList(history.getRedBall(), winLotteryVo.getRedBall()) && CollectionUtil.isEqualList(history.getBlueBall(), winLotteryVo.getBlueBall())) {
                return null;
            }
        }



        if (getAllDiffPeriodList(historyWin, 5, 1, winLotteryVo) == null) {
            return null;
        }
        if (getAllDiffPeriodList(historyWin, 5, null, winLotteryVo) == null) {
            return null;
        }
        if (getAllDiffPeriodList(historyWin, 4, 2, winLotteryVo) == null) {
            return null;
        }
        if (getAllDiffPeriodList(historyWin, 4, 1, winLotteryVo) == null) {
            return null;
        }
        if (getAllDiffPeriodList(historyWin, 4, null, winLotteryVo) == null) {
            return null;
        }

        if (getAllDiffPeriodList(historyWin, 3, 2, winLotteryVo) == null) {
            return null;
        }

        if (getAllDiffPeriodList(historyWin, 3, 1, winLotteryVo) == null) {
            return null;
        }
        if (getAllDiffPeriodList(historyWin, 3, null, winLotteryVo) == null) {
            return null;
        }


        return winLotteryVo;
    }

    // 获取5个红球号码，范围1到35
    private static List<Integer> getRedBalls() {
        // 获取前5个红球号码
        List<Integer> selectedRedBalls = new ArrayList<>();
        List<Integer> indexes = new ArrayList<>();
        while (true) {
            //随机从0到34中取一个数字
            Integer randomIndex = (int) (Math.random() * redBallList.size());
            if (indexes.contains(randomIndex)) {
                continue;
            }
            indexes.add(randomIndex);
            selectedRedBalls.add(redBallList.get(randomIndex));
            if (selectedRedBalls.size() >= 5) {
                break;
            }
        }

        // 对红球号码进行排序
        Collections.sort(selectedRedBalls);

        return selectedRedBalls;
    }

    // 获取1个蓝球号码，范围1到12
    public static List<Integer> getBlueBall() {
        // 获取前6个红球号码
        List<Integer> selectedRedBalls = new ArrayList<>(2);
        List<Integer> indexes = new ArrayList<>();
        while (true) {
            //随机从0到34中取一个数字
            Integer randomIndex = (int) (Math.random() * blueBallList.size());
            if (indexes.contains(randomIndex)) {
                continue;
            }
            indexes.add(randomIndex);
            selectedRedBalls.add(blueBallList.get(randomIndex));
            if (selectedRedBalls.size() >= 2) {
                break;
            }
        }
        // 对蓝色球号码进行排序
        Collections.sort(selectedRedBalls);
        return selectedRedBalls;
    }


}
